package com.only4play.portal.cp.api.impl;

import com.only4play.portal.common.bean.AccessToken;
import com.only4play.portal.common.error.PortalError;
import com.only4play.portal.common.error.PortalErrorException;
import com.only4play.portal.common.util.http.HttpType;
import com.only4play.portal.common.util.http.apache.ApacheHttpClientBuilder;
import com.only4play.portal.common.util.http.apache.DefaultApacheHttpClientBuilder;
import com.only4play.portal.cp.config.CpConfigStorage;
import com.only4play.portal.cp.constant.CpApiPathConstants;
import org.apache.hc.client5.http.classic.methods.HttpGet;
import org.apache.hc.client5.http.config.RequestConfig;
import org.apache.hc.client5.http.impl.classic.BasicHttpClientResponseHandler;
import org.apache.hc.client5.http.impl.classic.CloseableHttpClient;
import org.apache.hc.client5.http.impl.classic.CloseableHttpResponse;
import org.apache.hc.core5.http.HttpHost;

import java.io.IOException;

/**
 * @author liyuncong
 * @version 1.0
 * @file CpServiceApacheHttpClientImpl
 * @brief CpServiceApacheHttpClientImpl
 * @details CpServiceApacheHttpClientImpl
 * @date 2024-06-12
 *
 * Edit History
 * ----------------------------------------------------------------------------
 * DATE                     NAME               DESCRIPTION
 * 2024-06-12               liyuncong          Created
 */
public class CpServiceApacheHttpClientImpl extends BaseCpServiceImpl<CloseableHttpClient, HttpHost> {

    private CloseableHttpClient httpClient;
    private HttpHost httpProxy;

    @Override
    public CloseableHttpClient getRequestHttpClient() {
        return this.httpClient;
    }

    @Override
    public HttpHost getRequestHttpProxy() {
        return this.httpProxy;
    }

    @Override
    public HttpType getRequestType() {
        return HttpType.APACHE_HTTP;
    }

    @Override
    public void initHttp() {
        ApacheHttpClientBuilder apacheHttpClientBuilder = this.configStorage.getApacheHttpClientBuilder();
        if (apacheHttpClientBuilder == null) {
            apacheHttpClientBuilder = DefaultApacheHttpClientBuilder.getInstance();
        }

        apacheHttpClientBuilder.httpProxyHost(this.configStorage.getHttpProxyHost())
            .httpProxyPort(this.configStorage.getHttpProxyPort())
            .httpProxyUsername(this.configStorage.getHttpProxyUsername())
            .httpProxyPassword(this.configStorage.getHttpProxyPassword());

        if (this.configStorage.getHttpProxyHost() != null && this.configStorage.getHttpProxyPort() > 0) {
            this.httpProxy = new HttpHost(this.configStorage.getHttpProxyHost(), this.configStorage.getHttpProxyPort());
        }

        this.httpClient = apacheHttpClientBuilder.build();
    }

    @Override
    public CpConfigStorage getCpConfigStorage() {
        return this.configStorage;
    }

    @Override
    public String getAccessToken(boolean forceRefresh) throws PortalErrorException {
        if (!this.configStorage.isAccessTokenExpired() && !forceRefresh) {
            return this.configStorage.getAccessToken();
        }

        synchronized (this.globalAccessTokenRefreshLock) {
            // todo 调用接口获取accessToken
            try {
                String url = String.format(this.configStorage.getApiUrl(CpApiPathConstants.GET_TOKEN),
                    this.configStorage.getCorpId(), this.configStorage.getCorpSecret());

                HttpGet httpGet = new HttpGet(url);
                if (this.httpProxy != null) {
                    RequestConfig config = RequestConfig.custom()
                        .setProxy(this.httpProxy)
                        .build();
                    httpGet.setConfig(config);
                }

                String resultContent;
                try (CloseableHttpClient httpClient = getRequestHttpClient();
                     CloseableHttpResponse response = httpClient.execute(httpGet)) {
                    resultContent = new BasicHttpClientResponseHandler().handleResponse(response);
                }
                PortalError error = PortalError.fromJson(resultContent);
                if (error.getErrorCode() != 0) {
                    throw new PortalErrorException(error);
                }

                AccessToken accessToken = AccessToken.fromJson(resultContent);
                this.configStorage.updateAccessToken(accessToken.getAccessToken(), accessToken.getExpiresIn());

            } catch (IOException exception) {
                throw new RuntimeException("getAccessToken for url exception", exception);
            }
        }
        return this.configStorage.getAccessToken();
    }

}
